package com.demo.base.tokenLogin.token;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.demo.base.exception.AiException;
import com.demo.base.tokenLogin.model.UserDto;
import lombok.extern.slf4j.Slf4j;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static com.demo.constants.AppConstants.APP_SECRET;
import static com.demo.constants.AppConstants.TOKEN_EXPIRED_TIME;

/**
 * @author 曳戈泰尔
 * @version 1.0
 * @description JWT处理类
 * @date 2023/3/13 3:45 PM
 */
@Slf4j
public class JwtHelper {

    private static final String CLAIM_NAME = "token";

    /**
     * 生成token，自定义过期时间
     *
     * @param userTokenDTO
     * @return
     */
    public static String generateToken(UserDto userTokenDTO) {
        try {
            // 私钥和加密算法
            Algorithm algorithm = Algorithm.HMAC256(APP_SECRET);

            // 设置头部信息
            Map<String, Object> header = new HashMap<>(2);
            header.put("Type", "Jwt");
            header.put("alg", "HS256");

            // 设置过期时间，单位：MIN
            Calendar nowTime = Calendar.getInstance();
            nowTime.add(Calendar.MINUTE, TOKEN_EXPIRED_TIME);
            Date expiresDate = nowTime.getTime();

            return JWT.create()
                    .withHeader(header)
                    .withClaim(CLAIM_NAME, JSONObject.toJSONString(userTokenDTO))
                    .withExpiresAt(expiresDate)
                    .sign(algorithm);

        } catch (Exception e) {
            log.error("生成Token发生错误，原因：{}", e.getMessage());

            throw new AiException("登录失败，请重试");
        }
    }

    /**
     * 检验token是否正确
     *
     * @param token
     * @return
     */
    public static UserDto parseToken(String token) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(APP_SECRET);
            JWTVerifier verifier = JWT.require(algorithm).build();
            DecodedJWT jwt = verifier.verify(token);
            String tokenInfo = jwt.getClaim(CLAIM_NAME).asString();

            return JSON.parseObject(tokenInfo, UserDto.class);
        } catch (Exception ex) {
            log.error("解析Token失败，原因：{}", ex.getMessage());

            throw new AiException("登录已失效，请重新登录");
        }
    }
}
